package org.jiuling.netty.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.jiuling.basics.validation.Assertions;
import org.jiuling.netty.config.NettyServerConfig;

import java.net.InetSocketAddress;

/**
 * Netty服务
 * @author 紫灵
 * @date 2025年07月04日 00时03分13秒
 */
public class NettyServer {

    private final NettyServerConfig nettyServerConfig;
    /** 服务器引导 */
    private ServerBootstrap serverBootstrap;
    /** boss线程组 */
    private final NioEventLoopGroup bossThreadGroup;
    /** worker线程组 */
    private final NioEventLoopGroup workThreadGroup;
    /** 连接渠道 */
    private ChannelFuture channelFuture;

    public NettyServer(NettyServerConfig nettyServerConfig) {
        this.nettyServerConfig = nettyServerConfig;
        this.bossThreadGroup = new NioEventLoopGroup(nettyServerConfig.getBossThreadNumber());
        this.workThreadGroup = new NioEventLoopGroup(nettyServerConfig.getWorkThreadNumber());
    }

    /**
     * 构建服务器引导
     */
    public void construct(){
        this.serverBootstrap = new ServerBootstrap()
                .group(
                        // boss线程组，负责处理连接请求（即 accept 操作）
                        bossThreadGroup,
                        // worker线程组，负责处理已建立连接的数据读写操作（即 I/O 操作）。
                        workThreadGroup
                )
                // 选择服务器的ServerSocketChannel实现
                .channel(NioServerSocketChannel.class)
                // 服务器的监听端口
                .localAddress(
                        new InetSocketAddress(
                                nettyServerConfig.getHostName(),
                                nettyServerConfig.getPort()
                        )
                )
                // 工作线程处理器
                .childHandler(nettyServerConfig.getChannelInitializer());
    }

    /**
     * 启动服务
     */
    public void start(){
        Assertions.ObjectAssertions.isNotNull("请先构建服务器引导！",serverBootstrap);
        try {
            channelFuture = serverBootstrap.bind().sync();
//            channelFuture.channel();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            bossThreadGroup.shutdownGracefully();
            workThreadGroup.shutdownGracefully();
        }
    }

    public void stop(){

        try {
            channelFuture.channel().close().sync();

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            bossThreadGroup.shutdownGracefully();
            workThreadGroup.shutdownGracefully();
        }
    }


}
